﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RayTracing
{
    class Triangle : Geometry
    {
        P3 p1, p2, p3;
        float depth;
        P2 pa, pb, pc;

        public Triangle(P3 p1, P3 p2, P3 p3, float d) //3D triangles, triangles with depth!
        {
            this.p1 = p1;
            this.p2 = p2;
            this.p3 = p3;
            this.depth = d;
        }

        public float distance(Ray r)
        {
            P3 temp = barycentric(r);

            if (temp != null)
            {
                return (float)Math.Sqrt((temp.x - r.origin.x) * (temp.x - r.origin.x) + (temp.y - r.origin.y) * (temp.y - r.origin.y) + (temp.z - r.origin.z) * (temp.z - r.origin.z));
            }
            return Main.infinity;
        }

        public P3 barycentric (Ray r)
        //public P3 barycentric(Ray r, out float distance) //are we intersecting the triangle? This is currently for P3's
        {

            int ax = 0;
            int ay = 1;
            int az = 2;
            int axis;

            /* begin pseudo code */
            P3 a = P3.sub(p3, p2);
            P3 b = P3.sub(p3, p1);
            P3 c = P3.sub(p2, p1);
            P3 Normal = P3.cross(c, b);
            float dist = -P3.dot(P3.sub(r.origin, p1), Normal) / P3.dot(r.direction, Normal);

            // distance test
            //if ((distance < epsilon) || (distance > max_distance)) return false;

            // determine dominant axis
            if (Math.Abs(Normal.x) > Math.Abs(Normal.y))
            {
                if (Math.Abs(Normal.x) > Math.Abs(Normal.z)) axis = ax;
                else axis = az;
            }
            else
            {
                if (Math.Abs(Normal.y) > Math.Abs(Normal.z)) axis = ay;
                else axis = az;
            }
            // determine project plane axii
            int Uaxis = (axis + 1) % 3;
            int Vaxis = (axis + 2) % 3;
            // calculate hitpoint
            float Pu = P3.getAxis(r.origin, Uaxis) + dist * P3.getAxis(r.direction, Uaxis);
            float Pv = P3.getAxis(r.origin, Vaxis) + dist * P3.getAxis(r.direction, Vaxis);
            // check intersection
            float a2 = (P3.getAxis(b, Uaxis) * Pv - P3.getAxis(b, Vaxis) * Pu) / (P3.getAxis(b, Uaxis) * P3.getAxis(c, Vaxis) - P3.getAxis(b, Vaxis) * P3.getAxis(c, Uaxis));

            if (a2 < 0) return null;
            float a3 = (P3.getAxis(c, Vaxis) * Pu - P3.getAxis(c, Uaxis) * Pv) / (P3.getAxis(b, Uaxis) * P3.getAxis(c, Vaxis) - P3.getAxis(b, Vaxis) * P3.getAxis(c, Uaxis));
            if (a3 < 0) return null;
            if (a2 + a3 > 1) return null;

            float a1 = (1 - a2) - a3;

            // ray intersects triangle
            return new P3(a1, a2, a3);
            /* end pseudo code */
        }

        public P2 toP2(P3 p)
        {
            //barycentric(
            return new P2(p.x, p.y);
        }
        #region Geometry Members

        public P3 normal(P3 p)
        {
            return p;
        }

        #endregion

    }
}
